library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ROMPROG is
  Port ( AD : in  std_logic_vector (12 downto 0);
	 DO : out  std_logic_vector (15 downto 0);
	 CLK : in STD_LOGIC);
end ROMPROG;

architecture Behavioral of ROMPROG is
  constant low_address: natural := 0;
  constant high_address: natural := 8192;  
  subtype mot is std_logic_vector( 15 downto 0 );
  type zone_memoire is
    array (natural range low_address to high_address-1) of mot;
  constant m0: zone_memoire :=(
-- Test une partie du jeu d'instruction 
    0 => x"D404", --In R4
    1 => x"D405", --In R5
    2 => x"D740", --Out R5
    3 => x"D700",  --Out R4
    others => x"FFFF" --Reset
    );
constant m1: zone_memoire :=(
0 => x"C010", -- @0  C010 // LI R0, 2 @    0
1 => x"D401", -- D401 // IN R1 @    1
2 => x"E004", -- E004 // BRNE R0, R0 @    2
3 => x"FFFF", -- FFFF // RESET @    3
4 => x"6809", -- 6809 // SHR  R1, R1, 4 @    4
5 => x"CFF2", -- CFF2 // LI  R2, -2 @    5
6 => x"E08C", -- E08C // BRNE R1, R2 @    6
7 => x"FFFF", -- FFFF // RESET @    7
others => x"FFFF" --Reset
);

-- test INC
constant m2: zone_memoire :=(
-- Test une partie du jeu d'instruction 
    0 => x"D404", --In R4
	 -- R5 = R4 +1
    1 => "0" & "000010" & "000" & "100" & "101",
    2 => x"D740",  --Out R5
    others => x"FFFF" --Reset
    );

-- test DEC	 
constant m3: zone_memoire :=(
-- Test une partie du jeu d'instruction 
    0 => x"D404", --In R4
	 -- R4 = R4 -1
	 --           Dec         RB      RA      RD
    1 => "0" & "000011" & "000" & "100" & "100",
    2 => x"D700",  --Out R4
    others => x"FFFF" --Reset
    );

-- test ADD
constant m4: zone_memoire :=(
-- Test une partie du jeu d'instruction 

    -- In R2
    --                                   R2
    0  => "1101010" & "000" & "000" & "010",
	 
	 -- R3 = R2 - 1
	 --           Dec                  R2      R3
    1 => "0" & "000011" & "000" & "010" & "011",

	 -- R1 = R2 + R3
    --           Add         R3      R2      R1
    2	 => "0" & "000100" & "011" & "010" & "001",
	 
	 -- Out R1
    --                  R1   
    3	 => "1101011" & "001" & "000" & "000",

	 
    others => x"FFFF" --Reset
    );
	 
	 
-- test sub
constant m5: zone_memoire :=(
-- Test une partie du jeu d'instruction 

    -- In R2
    --                                   R2
    0  => "1101010" & "000" & "000" & "010",
	 
	 -- R3 = R2 - 1
	 --           Dec                  R2      R3
    1 => "0" & "000011" & "000" & "010" & "011",

	 -- R1 = R2 - R3
    --           Sub         R3      R2      R1
    2	 => "0" & "000101" & "011" & "010" & "001",
	 
	 -- Out R1
    --                  R1   
    3	 => "1101011" & "001" & "000" & "000",

	 
    others => x"FFFF" --Reset
    );
	 
-- test adc et shl
constant m6: zone_memoire :=(
-- Test une partie du jeu d'instruction 

    -- In R3 = 1
    --                                   R3
    0  => "1101010" & "000" & "000" & "011",
	 
	 -- on décale de 15 pour avoir x"8 0 0 0"
	 -- R2 = R3 << (14 + 1)
	 --           shl  decal=14(+1)         R3      R2
    1 => "0" & "10" & "1110" & "000" & "011" & "010",

	 -- R2 = R2 + R2
    --           Add         R3      R3      R3
    2	 => "0" & "000100" & "010" & "010" & "010",
	 
	 -- R3 = R3 +c R3
    --           Adc         R3      R3      R3
    3  => "0" & "000110" & "011" & "011" & "011",
	 
	 -- on affiche les 8 bits de poids forts de notre opérations gigantesque
	 -- 3 doit s'afficher
	 
	 -- Out R3 = 3
    --                  R3   
    4	 => "1101011" & "011" & "000" & "000",

	 
    others => x"FFFF" --Reset
    );


-- test mova et movb
constant m7: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1
	--                                   R1
	0  => "1101010" & "000" & "000" & "001",
	 
	-- Mova R0 -> R1
	--           mova              R1      R2
	1 => "0" & "001000" & "000" & "001" & "010",

	-- Movb R1 -> R2
	--           movb       R1             R2 
	2 => "0" & "001001" & "001" & "000" & "010",
	 
	 -- Out R2
	--       out       R2   
	3 => "1101011" & "010" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test nega
constant m8: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1
	--                                   R1
	0  => "1101010" & "000" & "000" & "001",
	 
	--nega R1 -> R1
	--           nega              R1      R1
	1 => "0" & "001010" & "000" & "001" & "001",
	 
	-- Out R1
	--       out       R1   
	2 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test negb
constant m9: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1
	--                                   R1
	0  => "1101010" & "000" & "000" & "001",
	 
	--negb R1 -> R1
	--           negb       R1             R1
	1 => "0" & "001011" & "001" & "000" & "001",
	 
	-- Out R1
	--       out       R1   
	2 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test and
constant m10: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1,  R1 = 6
	--                                 R1
	0  => "1101010" & "000" & "000" & "001",
	 
	-- R2 = R1 - 1
	--           Dec                R1      R2
   1 => "0" & "000011" & "000" & "001" & "010",
	 
	-- R1 -> R1 and R2
	--           and       R2      R1      R1
	2 => "0" & "010000" & "010" & "001" & "001",
	 
	-- Out R1, R1 = 4
	--       out       R1   
	3 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test or
constant m11: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1,  R1 = 6
	--                                 R1
	0  => "1101010" & "000" & "000" & "001",
	 
	-- R2 = R1 - 1
	--           Dec                R1      R2
   1 => "0" & "000011" & "000" & "001" & "010",
	 
	-- R1 -> R1 or R2
	--           or         R2      R1      R1
	2 => "0" & "010001" & "010" & "001" & "001",
	 
	-- Out R1, R1 = 7
	--       out       R1   
	3 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );

-- test xor
constant m12: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1,  R1 = 6
	--                                 R1
	0  => "1101010" & "000" & "000" & "001",
	 
	-- R2 = R1 - 1
	--           Dec                R1      R2
   1 => "0" & "000011" & "000" & "001" & "010",
	 
	-- R1 -> R1 xor R2
	--           xor        R2      R1      R1
	2 => "0" & "010010" & "010" & "001" & "001",
	 
	-- Out R1, R1 = 3
	--       out       R1   
	3 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test shr
constant m13: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1,  R1 = 8
	--                                 R1
	0  => "1101010" & "000" & "000" & "001",
	 
	-- R1 ->  R1 >> 3
	--          shr    2 + 1              R1      R1
	1 => "0" & "11" & "0010"  & "000" & "001" & "001",
	 
	-- Out R1, R1 = 1
	--       out       R1   
	2 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );

-- test not
constant m14: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- In R1,  R1 = 8
	--                                 R1
	0  => "1101010" & "000" & "000" & "001",
	 
	-- R1 =  ~ R1,
	--             not               R1      R1
	1 => "0" & "010011"  & "000" & "001" & "001",
	 
	-- Out R1, R1 = 1
	--       out       R1   
	2 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test lw sw
constant m15: zone_memoire :=(
-- Test une partie du jeu d'instruction 
	
	-- li R1 = 8
	--                   8        R1
	0  => "1100" & "000001000" & "001",
	 
	-- R2 = R1 - 1, R2 = 7
	--           Dec                R1      R2
   1 => "0" & "000011" & "000" & "001" & "010",
	
	-- MEM(R2) := R1
	--     sw                   R2      R1
	2 => "1101001"  & "000" & "010" & "001",
	
	-- R3 := MEM(R2)
	--     lw                   R2      R3
	3 => "1101000"  & "000" & "010" & "011",
	
	
	-- Out R3, R3 = 8
	--       out       R3   
	4 => "1101011" & "011" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test brcc
constant m16: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- li R1 = 8
	--                   8        R1
	0  => "1100" & "000001000" & "001",
	
	-- li R2 = 2
	--                   2        R2
	1  => "1100" & "000000010" & "010",
	 
	-- si R1 >= 0 on va ligne 4 (2 + R2)
	--                 R2      R1     >= 0
	2 => "1110000" & "010" & "001" & "001",
	
	-- R1 = R1 - 1, R1 = 7
	--           Dec                R1      R1
   3 => "0" & "000011" & "000" & "001" & "001",
	
	
	-- Out R1, R1 = 8
	--       out       R1   
	4 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );


-- test li
constant m17: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- li R1 = 8
	--                   8        R1
	0  => "1100" & "000001000" & "001",
	
	-- Out R1, R1 = 8
	--       out       R1   
	1 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );

-- test bacc
constant m18: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- li R1 = 8
	--                   8        R1
	0  => "1100" & "000001000" & "001",
	
	-- li R2 = 2
	--                   4        R2
	1  => "1100" & "000000100" & "010",
	 
	-- si R1 >= 0 on va ligne 4 (R2)
	--                 R2      R1     >= 0
	2 => "1110001" & "010" & "001" & "001",
	
	-- R1 = R1 - 1, R1 = 7
	--           Dec                R1      R1
   3 => "0" & "000011" & "000" & "001" & "001",
	
	
	-- Out R1, R1 = 8
	--       out       R1   
	4 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test bricc
constant m19: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- li R1 = 8
	--                   8        R1
	0  => "1100" & "000001000" & "001",
	 
	-- si R1 >= 0 on va ligne 3 (1+2)
	--                 2      R1     != 0
	1 => "10" & "00000010" & "001" & "100",
	
	-- R1 = R1 - 1, R1 = 7
	--           Dec                R1      R1
   2 => "0" & "000011" & "000" & "001" & "001",
	
	
	-- Out R1, R1 = 8
	--       out       R1   
	3 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test brl
constant m20: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- li R1 = 2
	--                   2        R1
	0  => "1100" & "000000010" & "001",
	 
	-- brl %r2 = 1 || %pc := 1 + R1
	--      brl        R1             R2
	1 => "1111000" & "001" & "000" & "010",
	
	-- R1 = R1 - 1, R1 = 1
	--           Dec                R1      R1
   2 => "0" & "000011" & "000" & "001" & "001",
	
	
	-- Out R1, R1 = 2
	--       out       R1   
	3 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );
	 
-- test bal
constant m21: zone_memoire :=(
-- Test une partie du jeu d'instruction 

	-- li R1 = 3
	--                   3         R1
	0  => "1100" & "000000011" & "001",
	 
	-- bal %r2 = 1 || %pc :=  R1
	--      brl        R1             R2
	1 => "1111001" & "001" & "000" & "010",
	
	-- R1 = R1 - 1, R1 = 1
	--           Dec                R1      R1
   2 => "0" & "000011" & "000" & "001" & "001",
	
	
	-- Out R1, R1 = 3
	--       out       R1   
	3 => "1101011" & "001" & "000" & "000",

	 
	others => x"FFFF" --Reset
    );

constant m22: zone_memoire :=(
-- PGCD
--0 li 120 dans R1*/*
	0 => "1100" & "001111000" & "001",

--1 li 12 dans R2*/
	1 => "1100" & "000001100" & "010",
	
--2 li %NUMERO INSTRUCTION SUIVANT MAIN_WHILE% dans R7 (6)
	2 => "1100" & "000000010" & "111",

--3 li %NUMERO INSTRUCTION SUIVANT MAIN_FIN_WHILE% dans R6 (13)
	3 => "1100" & "000001101" & "110",

--4 li %NUMERO INSTRUCTION SUIVANT MAIN_ELSE% dans R5 (11)
	4 => "1100" & "000001011" & "101",

--5 li %NUMERO INSTRUCTION SUIVANT FIN_IF% dans R4 (12)
	5 => "1100" & "000001100" & "100",

--6 R3 = R1-R2  */
	6 => "0" & "000101" & "010" & "001" & "011",

--7 bacc R3 valide == 0 (000), jmp vers R6*/
	7 => "1110001" & "110" & "011" & "000",

--8 bacc R3 valide > 0 (110), jmp vers R5
	8 => "1110001" & "101" & "011" & "110",

--9 R2 = R2-R1 */
	9 => "0" & "000101" & "001" & "010" & "010",

--10 bal vers R4 dans R0 (inutilisé)*/
	10 => "1111001" & "100" & "000" & "000",

--11 R1 = R1-R2 */
	11 => "0" & "000101" & "010" & "001" & "001",

--12 jmp vers R7*/
	12 => "1111001" & "111" & "000" & "000",
	
	-- li 511 dans R0*/*
	13 => "1100" & "000000001" & "000",
	
	-- MEM(R0) := R2
	--     sw                   R0      R2
	14 => "1101001"  & "000" & "000" & "010",
	
	-- Out R2, R2 = 5
	--       out       R2   
	15 => "1101011" & "010" & "000" & "000",

	others => x"FFFF" --Reset
	);
	 
  signal m: zone_memoire :=m22;
begin
  process(CLK)
  begin 
    if (CLK'event AND CLK='1') then
      DO <= m(conv_integer(AD));
    end if;
  end process;
end Behavioral;

